package com.yiquan.chat.service;

import java.util.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import com.yiquan.chat.dao.MessageDao;
import com.yiquan.chat.pojo.Message;

/**
 * 服务层
 *
 * @author Administrator
 */
@Service
public class MessageService {

    @Autowired
    private MessageDao messageDao;



    public static final int MSG_STATE_SEND = 0;
    public static final int MSG_STATE_SIGN = 1;
    public static final int MSG_STATE_DELETE = 2;


    @Autowired
    private RedisTemplate redisTemplate;

    private static final String CHAT_MODULE_ID = "CHAT_MODULE_ID";

    /**
     * 获取用户id (20000000-29999999)
     * @return
     */
    public Long getUniqueId() {
        redisTemplate.opsForValue().setIfAbsent(CHAT_MODULE_ID, 20000000L);
        Long temporaryUserId = redisTemplate.opsForValue().increment(CHAT_MODULE_ID);
        return temporaryUserId;
    }


    /**
     * 查询全部列表
     *
     * @return
     */
    public List<Message> findAll() {
        return messageDao.findAll();
    }


    /**
     * 条件查询+分页
     *
     * @param whereMap
     * @param page
     * @param size
     * @return
     */
    public Page<Message> findSearch(Map whereMap, int page, int size) {
        Specification<Message> specification = createSpecification(whereMap);
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        return messageDao.findAll(specification, pageRequest);
    }


    /**
     * 条件查询
     *
     * @param whereMap
     * @return
     */
    public List<Message> findSearch(Map whereMap) {
        Specification<Message> specification = createSpecification(whereMap);
        return messageDao.findAll(specification);
    }

    /**
     * 根据ID查询实体
     *
     * @param id
     * @return
     */
    public Message findById(Long id) {
        return messageDao.findById(id).get();
    }

    /**
     * 增加
     *
     * @param message
     */
    public void add(Message message) {
        message.setId(getUniqueId());
        messageDao.save(message);
    }

    /**
     * 修改
     *
     * @param message
     */
    public void update(Message message) {
        messageDao.save(message);
    }

    /**
     * 删除
     *
     * @param id
     */
    public void deleteById(Long id) {
        messageDao.deleteById(id);
    }

    /**
     * 动态条件构建
     *
     * @param searchMap
     * @return
     */
    private Specification<Message> createSpecification(Map searchMap) {

        return new Specification<Message>() {

            @Override
            public Predicate toPredicate(Root<Message> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList = new ArrayList<Predicate>();
                // 消息状态
                if (searchMap.get("msg_state") != null && !"".equals(searchMap.get("msg_state"))) {
                    predicateList.add(cb.equal(root.get("msg_state"), searchMap.get("msg_state")));
                }
                // 会话Id
                if (searchMap.get("converseId")!=null) {
                    predicateList.add(cb.equal(root.get("converse_id"), (Long)searchMap.get("converseId")));

                }
                return cb.and(predicateList.toArray(new Predicate[predicateList.size()]));

            }
        };

    }

    /**
     * 批量更新聊天状态
     *
     * @param userIds
     * @param i
     */
    public void updateMessageListByUserId(List<Long> userIds, int i) {
        Specification<Message> specification = (Root<Message> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            CriteriaBuilder.In<Object> user_id = cb.in(root.get("user_id"));
            return user_id.in(user_id);
        };
        List<Message> messages = messageDao.findAll(specification);
        for (Message message : messages) {
            message.setMsg_state(i + "");
        }

    }

    public Message getLastMsgByConverseId(Long converseId) {
        return messageDao.getLastMsgByConverseId(converseId);
    }

    public void updateMessageListByMsgId(List<Long> msgIds, int i) {
        Specification<Message> specification = (Root<Message> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            CriteriaBuilder.In<Object> msg_id = cb.in(root.get("msg_id"));
            return msg_id.in(msgIds);
        };
        List<Message> messages = messageDao.findAll(specification);
        if (MessageService.MSG_STATE_SIGN == i) {
            for (Message message : messages) {
                message.setMsg_state(i + "");
                message.setMsg_receive_date(new Date());
            }
        } else {
            for (Message message : messages) {
                message.setMsg_state(i + "");
            }
        }
        messageDao.saveAll(messages);
    }

    public List<Message> getUnDeleteMessageByConverseId(Long converseId) {
        return messageDao.getUnDeleteMessageByConverseId(converseId);
    }

    public Page<Message> getMsgByConverseId(Long converseId,int page, int size) {
        Map map = new HashMap();
        map.put("converseId", converseId);
        Specification<Message> specification = this.createSpecification(map);
        PageRequest pageRequest = PageRequest.of(page - 1, size,Sort.by(Sort.Direction.DESC, "msgSendDate"));
        return messageDao.findAll(specification,pageRequest);
    }

    public Integer countUnReadMsgByConverseId(Long converseId) {
        return messageDao.countUnReadMsgByConverseId(converseId);
    }

    public List<Message> getUnReadMsgByConverseId(Long converseId) {
        return messageDao.getUnReadMsgByConverseId(converseId);
    }

    public void readUnReadMsgByConverseId(Long converseId){
        messageDao.updateMsgUnreadStatus(converseId,new Date());
    }
}
